Passed
Push — master ( eee927...0d02ce )
by Rafael S.
01:31
created

bit-packer.js ➔ packCrumbs   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 16
rs 9.4285
1
/*
2
 * bit-packer: Pack and unpack nibbles, crumbs and booleans into bytes.
3
 * Copyright (c) 2017 Rafael da Silva Rocha.
4
 * https://github.com/rochars/byte-data
5
 */
6
7
let helpers = require("../src/helpers.js");
8
9
/**
10
 * Pack 2 nibbles in 1 byte.
11
 * @param {!Array<number>} nibbles Array of nibbles.
12
 * @return {!Array<number>} Pairs of neebles packed as one byte.
13
 */
14
function packNibbles(nibbles) {
15
    let packed = [];
16
    let i = 0;
17
    let j = 0;
18
    let len = nibbles.length;
19
    if (len % 2) {
20
        nibbles.push(0);
21
    }
22
    while (i < len) {
23
        packed[j++] = parseInt(
24
            nibbles[i].toString(16) + nibbles[i+1].toString(16), 16);
25
        i+=2;
26
    }
27
    return packed;
28
}
29
30
/**
31
 * Unpack a byte into 2 nibbles.
32
 * @param {!Array<number>|Uint8Array} bytes Array of bytes.
33
 * @return {!Array<number>} The nibbles.
34
 */
35
function unpackNibbles(bytes) {
36
    let unpacked = [];
37
    let i = 0;
38
    let j = 0;
39
    let len = bytes.length;
40
    while (i < len) {
41
        unpacked[j++] = parseInt(bytes[i].toString(16)[0], 16);
42
        unpacked[j++] = parseInt(bytes[i].toString(16)[1], 16);
43
        i++;
44
    }
45
    return unpacked;
46
}
47
48
/**
49
 * Pack 4 crumbs in 1 byte.
50
 * @param {!Array<number>} crumbs Array of crumbs.
51
 * @return {!Array<number>} 4 crumbs packed as one byte.
52
 */
53
function packCrumbs(crumbs) {
54
    let packed = [];
55
    let i = 0;
56
    let j = 0;
57
    fixByteArraySize(crumbs, 4);
58
    let len = crumbs.length - 3;
59
    while (i < len) {
60
        packed[j++] = parseInt(
61
            helpers.lPadZeros(crumbs[i].toString(2), 2) +
62
            helpers.lPadZeros(crumbs[i+1].toString(2), 2) +
63
            helpers.lPadZeros(crumbs[i+2].toString(2), 2) +
64
            helpers.lPadZeros(crumbs[i+3].toString(2), 2), 2);
65
        i+=4;
66
    }
67
    return packed;
68
}
69
70
/**
71
 * Unpack a byte into 4 crumbs.
72
 * @param {!Array<number>|Uint8Array} crumbs Array of bytes.
73
 * @return {!Array<number>} The crumbs.
74
 */
75
function unpackCrumbs(crumbs) {
76
    let unpacked = [];
77
    let i = 0;
78
    let j = 0;
79
    let len = crumbs.length;
80
    let bitCrumb;
81
    while (i < len) {
82
        bitCrumb = helpers.lPadZeros(crumbs[i].toString(2), 8);
83
        unpacked[j++] = parseInt(bitCrumb[0] + bitCrumb[1], 2);
84
        unpacked[j++] = parseInt(bitCrumb[2] + bitCrumb[3], 2);
85
        unpacked[j++] = parseInt(bitCrumb[4] + bitCrumb[5], 2);
86
        unpacked[j++] = parseInt(bitCrumb[6] + bitCrumb[7], 2);
87
        i++;
88
    }
89
    return unpacked;
90
}
91
92
/**
93
 * Pack 8 booleans in 1 byte.
94
 * @param {!Array<number>} booleans Array of booleans.
95
 * @return {!Array<number>} 4 crumbs packed as one byte.
96
 */
97
function packBooleans(booleans) {
98
    let packed = [];
99
    let i = 0;
100
    let j = 0;
101
    fixByteArraySize(booleans, 8);
102
    let len = booleans.length - 7;
103
    while (i < len) {
104
        packed[j++] = parseInt(
105
            booleans[i].toString(2) +
106
            booleans[i+1].toString(2) +
107
            booleans[i+2].toString(2) +
108
            booleans[i+3].toString(2) +
109
            booleans[i+4].toString(2) +
110
            booleans[i+5].toString(2) +
111
            booleans[i+6].toString(2) +
112
            booleans[i+7].toString(2), 2);
113
        i+=8;
114
    }
115
    return packed;
116
}
117
118
/**
119
 * Unpack a byte into 8 booleans.
120
 * @param {!Array<number>|Uint8Array} booleans Array of bytes.
121
 * @return {!Array<number>} The booleans.
122
 */
123
function unpackBooleans(booleans) {
124
    let unpacked = [];
125
    let i = 0;
126
    let j = 0;
127
    let len = booleans.length;
128
    let bitBoolean;
129
    while (i < len) {
130
        bitBoolean = helpers.lPadZeros(booleans[i].toString(2), 8);
131
        unpacked[j++] = parseInt(bitBoolean[0], 2);
132
        unpacked[j++] = parseInt(bitBoolean[1], 2);
133
        unpacked[j++] = parseInt(bitBoolean[2], 2);
134
        unpacked[j++] = parseInt(bitBoolean[3], 2);
135
        unpacked[j++] = parseInt(bitBoolean[4], 2);
136
        unpacked[j++] = parseInt(bitBoolean[5], 2);
137
        unpacked[j++] = parseInt(bitBoolean[6], 2);
138
        unpacked[j++] = parseInt(bitBoolean[7], 2);
139
        i++;
140
    }
141
    return unpacked;
142
}
143
144
/**
145
 * Pad a array with zeros to the right.
146
 * @param {!Array<number>} byteArray The array.
147
 * @param {number} numZeros the max number of zeros.
148
 *      For 1 binary byte string it should be 8.
149
 *      TODO: better explanation of numZeros
150
 */
151
function fixByteArraySize(byteArray, numZeros) {
152
    let i = 0;
153
    let fix = byteArray.length % numZeros;
154
    if (fix) {
155
        fix = (fix - numZeros) * -1;
156
        while(i < fix) {
157
            byteArray.push(0);
158
            i++;
159
        }
160
    }
161
}
162
163
module.exports.packBooleans = packBooleans;
164
module.exports.unpackBooleans = unpackBooleans;
165
module.exports.packCrumbs = packCrumbs;
166
module.exports.unpackCrumbs = unpackCrumbs;
167
module.exports.packNibbles = packNibbles;
168
module.exports.unpackNibbles = unpackNibbles;
169